package ink.tiptop.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Map;

/**
 * @author Tiptop_ZJF
 * @ClassName: BeanConvertUtil
 * @DESC
 * @Date: 2019/8/23 9:29
 * @since JDK 1.8
 */
@Slf4j
public class BeanConvertUtil {

    private final static ObjectMapper objectMapper = new ObjectMapper();

    public static <T> T mapToBean(Map map, Class clazz) {
        return (T) JSON.map2pojo(map, clazz);
    }

    public static <T> Map beanToMap(T t) {
        return JSON.obj2pojo(t, Map.class);
    }

    /**
     * 忽略名称匹配 默认一对一赋值
     * 字段数量以source为准
     * 2019年9月11日10:05:55
     * zjf
     *
     * @param source
     * @param target
     */
    public static <T> T ignoreNameMap(Object source, T target) {
        try {
            Class<?> clazz1 = source.getClass();
            Field[] declaredFields1 = clazz1.getDeclaredFields();
            Class<?> clazz2 = target.getClass();
            Field[] declaredFields2 = clazz2.getDeclaredFields();
            for (int i = 0; i < declaredFields1.length; i++) {
                declaredFields1[i].setAccessible(true);
                Object obj1Value = declaredFields1[i].get(source);
                if (declaredFields2[i] != null) {
                    declaredFields2[i].setAccessible(true);
                    declaredFields2[i].set(target, obj1Value);
                }
            }
        } catch (Exception e) {
            log.error("", e);
        }
        return target;
    }

    /**
     * 下划线字段对象 转 驼峰字段对象
     *
     * @param lineObj
     * @param camelObj
     * @param <T>
     * @return
     */
    public static <T> T lineToCamel(Object lineObj, T camelObj) {
        Class<?> camelClazz = camelObj.getClass();
        Class<?> lineClazz = lineObj.getClass();
        Field[] lineFields = lineClazz.getDeclaredFields();
        for (Field lineField : lineFields) {
            try {
                lineField.setAccessible(true);
                String lineFieldName = lineField.getName().toLowerCase();
                String camelFieldName = lineToCamelName(lineFieldName);
                Field camelField = camelClazz.getDeclaredField(camelFieldName);
                camelField.setAccessible(true);
                camelField.set(camelObj, lineField.get(lineObj));
            } catch (IllegalAccessException e) {
                log.error("", e);
            } catch (NoSuchFieldException e) {
                log.error("", e);
            } catch (Exception e) {
                log.error("", e);
            }
        }
        return camelObj;
    }

    private static String lineToCamelName(String lineName) {
        StringBuilder sb = new StringBuilder();
        final String line = "_";
        if (!lineName.contains(line)) {
            return lineName;
        }
        String[] names = lineName.split(line);
        for (int i = 0; i < names.length; i++) {
            if (i == 0) {
                sb.append(names[i]);
            } else {
                sb.append(firstLetterToUpperCase(names[i]));
            }
        }
        return sb.toString();
    }

    /**
     * 第二个单词开始首字母大写
     *
     * @param word
     * @return
     */
    private static String firstLetterToUpperCase(String word) {
        StringBuilder sb = new StringBuilder();
        String firstLetter = word.substring(0, 1);
        String upperCase = firstLetter.toUpperCase();
        String lowerCase = word.substring(1);
        return sb.append(upperCase).append(lowerCase).toString();
    }

    /**
     * 驼峰字段对象 转 下划线字段对象
     *
     * @param camelObj
     * @param lineObj
     * @param <T>
     * @return
     */
    public static <T> T camelToLine(Object camelObj, T lineObj) {
        Class<?> lineClazz = lineObj.getClass();
        Class<?> camelClazz = camelObj.getClass();
        Field[] camelFields = camelClazz.getDeclaredFields();
        for (Field camelField : camelFields) {
            try {
                camelField.setAccessible(true);
                String camelFieldName = camelField.getName();
                String lineFieldName = camelToLineName(camelFieldName);
                System.out.println(lineFieldName);
                Field lineField = lineClazz.getDeclaredField(lineFieldName);
                lineField.setAccessible(true);
                lineField.set(lineObj, camelField.get(camelObj));
            } catch (IllegalAccessException e) {
                log.error("", e);
            } catch (NoSuchFieldException e) {
                log.error("", e);
            } catch (Exception e) {
                log.error("", e);
            }
        }
        return lineObj;
    }

    /**
     * 单词首字母大写
     *
     * @param camelName
     * @return
     */
    private static String camelToLineName(String camelName) {
        StringBuilder sb = new StringBuilder();
        // 查找大写字母的位置
        char[] ch = camelName.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            if (i == 0) {
                sb.append(ch[i]);
                continue;
            }
            if ((int) ch[i] >= 65 && (int) ch[i] <= 90) {
                sb.append("_").append(charToLower(ch[i]));
            } else {
                sb.append(ch[i]);
            }
        }
        return sb.toString();
    }

    /**
     * 大写字符转小写字符
     *
     * @param ch
     * @return
     */
    private static char charToLower(char ch) {
        return ch += 32;
    }
}
